package cn.sskxyz.mongodb.compress;

import java.util.List;

import org.bson.BsonDocument;
import org.bson.Document;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.conversions.Bson;

import com.mongodb.MongoNamespace;
import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
import com.mongodb.bulk.BulkWriteResult;
import com.mongodb.client.AggregateIterable;
import com.mongodb.client.ChangeStreamIterable;
import com.mongodb.client.ClientSession;
import com.mongodb.client.DistinctIterable;
import com.mongodb.client.FindIterable;
import com.mongodb.client.ListIndexesIterable;
import com.mongodb.client.MapReduceIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.model.BulkWriteOptions;
import com.mongodb.client.model.CountOptions;
import com.mongodb.client.model.CreateIndexOptions;
import com.mongodb.client.model.DeleteOptions;
import com.mongodb.client.model.DropIndexOptions;
import com.mongodb.client.model.EstimatedDocumentCountOptions;
import com.mongodb.client.model.FindOneAndDeleteOptions;
import com.mongodb.client.model.FindOneAndReplaceOptions;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.IndexModel;
import com.mongodb.client.model.IndexOptions;
import com.mongodb.client.model.InsertManyOptions;
import com.mongodb.client.model.InsertOneOptions;
import com.mongodb.client.model.RenameCollectionOptions;
import com.mongodb.client.model.ReplaceOptions;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.model.WriteModel;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.InsertManyResult;
import com.mongodb.client.result.InsertOneResult;
import com.mongodb.client.result.UpdateResult;

public abstract class AbstractMongoCollection<TDocument> implements MongoCollection<TDocument> {
	
	public abstract MongoCollection<TDocument> getMongoCollection();

	@Override
	public MongoNamespace getNamespace() {
		return getMongoCollection().getNamespace();
	}

	@Override
	public Class<TDocument> getDocumentClass() {
		return getMongoCollection().getDocumentClass();
	}

	@Override
	public CodecRegistry getCodecRegistry() {
		return getMongoCollection().getCodecRegistry();
	}

	@Override
	public ReadPreference getReadPreference() {
		return getMongoCollection().getReadPreference();
	}

	@Override
	public WriteConcern getWriteConcern() {
		return getMongoCollection().getWriteConcern();
	}

	@Override
	public ReadConcern getReadConcern() {
		return getMongoCollection().getReadConcern();
	}

	@Override
	public <NewTDocument> MongoCollection<NewTDocument> withDocumentClass(Class<NewTDocument> clazz) {
		return getMongoCollection().withDocumentClass(clazz);
	}

	@Override
	public MongoCollection<TDocument> withCodecRegistry(CodecRegistry codecRegistry) {
		getMongoCollection().withCodecRegistry(codecRegistry);
		return this;
	}

	@Override
	public MongoCollection<TDocument> withReadPreference(ReadPreference readPreference) {
		 getMongoCollection().withReadConcern(getReadConcern());
		 return this;
	}

	@Override
	public MongoCollection<TDocument> withWriteConcern(WriteConcern writeConcern) {
		  getMongoCollection().withWriteConcern(writeConcern);
		return this;
	}

	@Override
	public MongoCollection<TDocument> withReadConcern(ReadConcern readConcern) {
		  getMongoCollection().withReadConcern(readConcern);
		return this;
	}

	@Override
	public long countDocuments() {
		return getMongoCollection().countDocuments();
	}

	@Override
	public long countDocuments(Bson filter) {
		return getMongoCollection().countDocuments(filter);
	}

	@Override
	public long countDocuments(Bson filter, CountOptions options) {
		return getMongoCollection().countDocuments(filter, options);
	}

	@Override
	public long countDocuments(ClientSession clientSession) {
		return getMongoCollection().countDocuments(clientSession);
	}

	@Override
	public long countDocuments(ClientSession clientSession, Bson filter) {
		return getMongoCollection().countDocuments(clientSession, filter);
	}

	@Override
	public long countDocuments(ClientSession clientSession, Bson filter, CountOptions options) {
		return getMongoCollection().countDocuments(clientSession, filter, options);
	}

	@Override
	public long estimatedDocumentCount() {
		return getMongoCollection().estimatedDocumentCount();
	}

	@Override
	public long estimatedDocumentCount(EstimatedDocumentCountOptions options) {
		return getMongoCollection().estimatedDocumentCount(options);
	}

	@Override
	public <TResult> DistinctIterable<TResult> distinct(String fieldName, Class<TResult> resultClass) {
		return getMongoCollection().distinct(fieldName, resultClass);
	}

	@Override
	public <TResult> DistinctIterable<TResult> distinct(String fieldName, Bson filter, Class<TResult> resultClass) {
		return getMongoCollection().distinct(fieldName, filter, resultClass);
	}

	@Override
	public <TResult> DistinctIterable<TResult> distinct(ClientSession clientSession, String fieldName,
			Class<TResult> resultClass) {
		return getMongoCollection().distinct(clientSession, fieldName, resultClass);
	}

	@Override
	public <TResult> DistinctIterable<TResult> distinct(ClientSession clientSession, String fieldName, Bson filter,
			Class<TResult> resultClass) {
		return getMongoCollection().distinct(clientSession, fieldName, filter, resultClass);
	}

	@Override
	public FindIterable<TDocument> find() {
		return this.find(new BsonDocument(), getMongoCollection().getDocumentClass());
	}

	@Override
	public <TResult> FindIterable<TResult> find(Class<TResult> resultClass) {
		return this.find(new BsonDocument(), resultClass);
	}

	@Override
	public FindIterable<TDocument> find(Bson filter) {
		return this.find(filter, getMongoCollection().getDocumentClass());
	}

	@Override
	public FindIterable<TDocument> find(ClientSession clientSession) {
		return find(clientSession, new BsonDocument(), getMongoCollection().getDocumentClass());
	}

	@Override
	public <TResult> FindIterable<TResult> find(ClientSession clientSession, Class<TResult> resultClass) {
		return this.find(clientSession, new BsonDocument(), resultClass);
	}

	@Override
	public FindIterable<TDocument> find(ClientSession clientSession, Bson filter) {
		return this.find(clientSession, filter, getMongoCollection().getDocumentClass());
	}

	@Override
	public AggregateIterable<TDocument> aggregate(List<? extends Bson> pipeline) {
		return getMongoCollection().aggregate(pipeline);
	}

	@Override
	public <TResult> AggregateIterable<TResult> aggregate(List<? extends Bson> pipeline, Class<TResult> resultClass) {
		return null;
	}

	@Override
	public AggregateIterable<TDocument> aggregate(ClientSession clientSession, List<? extends Bson> pipeline) {
		return getMongoCollection().aggregate(clientSession, pipeline);
	}

	@Override
	public <TResult> AggregateIterable<TResult> aggregate(ClientSession clientSession, List<? extends Bson> pipeline,
			Class<TResult> resultClass) {
		return getMongoCollection().aggregate(clientSession, pipeline, resultClass);
	}

	@Override
	public ChangeStreamIterable<TDocument> watch() {
		return getMongoCollection().watch();
	}

	@Override
	public <TResult> ChangeStreamIterable<TResult> watch(Class<TResult> resultClass) {
		return getMongoCollection().watch(resultClass);
	}

	@Override
	public ChangeStreamIterable<TDocument> watch(List<? extends Bson> pipeline) {
		return getMongoCollection().watch(pipeline);
	}

	@Override
	public <TResult> ChangeStreamIterable<TResult> watch(List<? extends Bson> pipeline, Class<TResult> resultClass) {
		return getMongoCollection().watch(pipeline, resultClass);
	}

	@Override
	public ChangeStreamIterable<TDocument> watch(ClientSession clientSession) {
		return getMongoCollection().watch(clientSession);
	}

	@Override
	public <TResult> ChangeStreamIterable<TResult> watch(ClientSession clientSession, Class<TResult> resultClass) {
		return getMongoCollection().watch(clientSession, resultClass);
	}

	@Override
	public ChangeStreamIterable<TDocument> watch(ClientSession clientSession, List<? extends Bson> pipeline) {
		return getMongoCollection().watch(clientSession, pipeline);
	}

	@Override
	public <TResult> ChangeStreamIterable<TResult> watch(ClientSession clientSession, List<? extends Bson> pipeline,
			Class<TResult> resultClass) {
		return getMongoCollection().watch(clientSession, pipeline, resultClass);
	}

	@Override
	public MapReduceIterable<TDocument> mapReduce(String mapFunction, String reduceFunction) {
		return getMongoCollection().mapReduce(mapFunction, reduceFunction);
	}

	@Override
	public <TResult> MapReduceIterable<TResult> mapReduce(String mapFunction, String reduceFunction,
			Class<TResult> resultClass) {
		return getMongoCollection().mapReduce(mapFunction, reduceFunction, resultClass);
	}

	@Override
	public MapReduceIterable<TDocument> mapReduce(ClientSession clientSession, String mapFunction,
			String reduceFunction) {
		return getMongoCollection().mapReduce(clientSession, mapFunction, reduceFunction);
	}

	@Override
	public <TResult> MapReduceIterable<TResult> mapReduce(ClientSession clientSession, String mapFunction,
			String reduceFunction, Class<TResult> resultClass) {
		return getMongoCollection().mapReduce(clientSession, mapFunction, reduceFunction, resultClass);
	}

	@Override
	public BulkWriteResult bulkWrite(List<? extends WriteModel<? extends TDocument>> requests) {
		return getMongoCollection().bulkWrite(requests);
	}

	@Override
	public BulkWriteResult bulkWrite(List<? extends WriteModel<? extends TDocument>> requests,
			BulkWriteOptions options) {
		return getMongoCollection().bulkWrite(requests, options);
	}

	@Override
	public BulkWriteResult bulkWrite(ClientSession clientSession,
			List<? extends WriteModel<? extends TDocument>> requests) {
		return getMongoCollection().bulkWrite(clientSession, requests);
	}

	@Override
	public BulkWriteResult bulkWrite(ClientSession clientSession,
			List<? extends WriteModel<? extends TDocument>> requests, BulkWriteOptions options) {
		return getMongoCollection().bulkWrite(clientSession, requests, options);
	}

	@Override
	public InsertOneResult insertOne(TDocument document) {
		return this.insertOne(document, new InsertOneOptions());
	}

    @Override
    public InsertOneResult insertOne(final ClientSession clientSession, final TDocument document) {
        return insertOne(clientSession, document, new InsertOneOptions());
    }

    @Override
	public InsertManyResult insertMany(List<? extends TDocument> documents) {
		return this.insertMany(documents, new InsertManyOptions());
	}

	@Override
	public InsertManyResult insertMany(ClientSession clientSession, List<? extends TDocument> documents) {
		return this.insertMany(clientSession, documents, new InsertManyOptions());
	}

	
	@Override
	public DeleteResult deleteOne(Bson filter) {
		return getMongoCollection().deleteOne(filter);
	}

	@Override
	public DeleteResult deleteOne(Bson filter, DeleteOptions options) {
		return getMongoCollection().deleteOne(filter, options);
	}

	@Override
	public DeleteResult deleteOne(ClientSession clientSession, Bson filter) {
		return getMongoCollection().deleteOne(clientSession, filter);
	}

	@Override
	public DeleteResult deleteOne(ClientSession clientSession, Bson filter, DeleteOptions options) {
		return getMongoCollection().deleteOne(clientSession, filter, options);
	}

	@Override
	public DeleteResult deleteMany(Bson filter) {
		return getMongoCollection().deleteMany(filter);
	}

	@Override
	public DeleteResult deleteMany(Bson filter, DeleteOptions options) {
		return getMongoCollection().deleteMany(filter, options);
	}

	@Override
	public DeleteResult deleteMany(ClientSession clientSession, Bson filter) {
		return getMongoCollection().deleteMany(clientSession, filter);
	}

	@Override
	public DeleteResult deleteMany(ClientSession clientSession, Bson filter, DeleteOptions options) {
		return getMongoCollection().deleteMany(clientSession, filter, options);
	}

	@Override
	public UpdateResult replaceOne(Bson filter, TDocument replacement) {
		return this.replaceOne(filter, replacement, new ReplaceOptions());
	}

	@Override
	public UpdateResult replaceOne(ClientSession clientSession, Bson filter, TDocument replacement) {
		return this.replaceOne(clientSession, filter, replacement, new ReplaceOptions());
	}

	@Override
	public UpdateResult updateOne(Bson filter, Bson update) {
		return this.updateOne(filter, update, new UpdateOptions());
	}

	@Override
	public UpdateResult updateOne(ClientSession clientSession, Bson filter, Bson update) {
		return this.updateOne(clientSession, filter, update, new UpdateOptions());
	}

	@Override
	public UpdateResult updateOne(Bson filter, List<? extends Bson> update) {
		return this.updateOne(filter, update, new UpdateOptions());
	}

	@Override
	public UpdateResult updateOne(ClientSession clientSession, Bson filter, List<? extends Bson> update) {
		return this.updateOne(clientSession, filter, update, new UpdateOptions());
	}

	@Override
	public UpdateResult updateOne(ClientSession clientSession, Bson filter, List<? extends Bson> update,
			UpdateOptions updateOptions) {
		return getMongoCollection().updateOne(clientSession, filter, update, updateOptions);
	}

	@Override
	public UpdateResult updateMany(Bson filter, Bson update) {
		return this.updateMany(filter, update, new UpdateOptions());
	}

	@Override
	public UpdateResult updateMany(ClientSession clientSession, Bson filter, Bson update) {
		return this.updateMany(clientSession, filter, update, new UpdateOptions());
	}

	@Override
	public UpdateResult updateMany(Bson filter, List<? extends Bson> update) {
		return getMongoCollection().updateMany(filter, update);
	}

	@Override
	public UpdateResult updateMany(ClientSession clientSession, Bson filter, List<? extends Bson> update) {
		return getMongoCollection().updateMany(clientSession, filter, update);
	}

	@Override
	public UpdateResult updateMany(ClientSession clientSession, Bson filter, List<? extends Bson> update,
			UpdateOptions updateOptions) {
		return getMongoCollection().updateMany(clientSession, filter, update, updateOptions);
	}

	@Override
	public TDocument findOneAndDelete(Bson filter) {
		return getMongoCollection().findOneAndDelete(filter);
	}

	@Override
	public TDocument findOneAndDelete(Bson filter, FindOneAndDeleteOptions options) {
		return getMongoCollection().findOneAndDelete(filter, options);
	}

	@Override
	public TDocument findOneAndDelete(ClientSession clientSession, Bson filter) {
		return getMongoCollection().findOneAndDelete(clientSession, filter);
	}

	@Override
	public TDocument findOneAndDelete(ClientSession clientSession, Bson filter, FindOneAndDeleteOptions options) {
		return getMongoCollection().findOneAndDelete(clientSession, filter);
	}

	@Override
	public TDocument findOneAndReplace(Bson filter, TDocument replacement) {
		return this.findOneAndReplace(filter, replacement, new FindOneAndReplaceOptions());
	}

	@Override
	public TDocument findOneAndReplace(ClientSession clientSession, Bson filter, TDocument replacement) {
		return this.findOneAndReplace(clientSession, filter, replacement, new FindOneAndReplaceOptions());
	}

	@Override
	public TDocument findOneAndUpdate(Bson filter, Bson update) {
		return this.findOneAndUpdate(filter, update, new FindOneAndUpdateOptions());
	}

	@Override
	public TDocument findOneAndUpdate(ClientSession clientSession, Bson filter, Bson update) {
		return this.findOneAndUpdate(clientSession, filter, update, new FindOneAndUpdateOptions());
	}

	@Override
	public TDocument findOneAndUpdate(Bson filter, List<? extends Bson> update) {
		return getMongoCollection().findOneAndUpdate(filter, update);
	}

	@Override
	public TDocument findOneAndUpdate(Bson filter, List<? extends Bson> update, FindOneAndUpdateOptions options) {
		return getMongoCollection().findOneAndUpdate(filter, update, options);
	}

	@Override
	public TDocument findOneAndUpdate(ClientSession clientSession, Bson filter, List<? extends Bson> update) {
		return getMongoCollection().findOneAndUpdate(clientSession, filter, update);
	}

	@Override
	public TDocument findOneAndUpdate(ClientSession clientSession, Bson filter, List<? extends Bson> update,
			FindOneAndUpdateOptions options) {
		return getMongoCollection().findOneAndUpdate(clientSession, filter, update, options);
	}

	@Override
	public void drop() {
		getMongoCollection().drop();
	}

	@Override
	public void drop(ClientSession clientSession) {
		getMongoCollection().drop(clientSession);
	}

	@Override
	public String createIndex(Bson keys) {
		return getMongoCollection().createIndex(keys);
	}

	@Override
	public String createIndex(Bson keys, IndexOptions indexOptions) {
		return getMongoCollection().createIndex(keys, indexOptions);
	}

	@Override
	public String createIndex(ClientSession clientSession, Bson keys) {
		return getMongoCollection().createIndex(clientSession, keys);
	}

	@Override
	public String createIndex(ClientSession clientSession, Bson keys, IndexOptions indexOptions) {
		return getMongoCollection().createIndex(clientSession, keys, indexOptions);
	}

	@Override
	public List<String> createIndexes(List<IndexModel> indexes) {
		return getMongoCollection().createIndexes(indexes);
	}

	@Override
	public List<String> createIndexes(List<IndexModel> indexes, CreateIndexOptions createIndexOptions) {
		return getMongoCollection().createIndexes(indexes, createIndexOptions);
	}

	@Override
	public List<String> createIndexes(ClientSession clientSession, List<IndexModel> indexes) {
		return getMongoCollection().createIndexes(clientSession, indexes);
	}

	@Override
	public List<String> createIndexes(ClientSession clientSession, List<IndexModel> indexes,
			CreateIndexOptions createIndexOptions) {
		return getMongoCollection().createIndexes(clientSession, indexes, createIndexOptions);
	}

	@Override
	public ListIndexesIterable<Document> listIndexes() {
		return getMongoCollection().listIndexes();
	}

	@Override
	public <TResult> ListIndexesIterable<TResult> listIndexes(Class<TResult> resultClass) {
		return getMongoCollection().listIndexes(resultClass);
	}

	@Override
	public ListIndexesIterable<Document> listIndexes(ClientSession clientSession) {
		return getMongoCollection().listIndexes(clientSession);
	}

	@Override
	public <TResult> ListIndexesIterable<TResult> listIndexes(ClientSession clientSession, Class<TResult> resultClass) {
		return getMongoCollection().listIndexes(clientSession, resultClass);
	}

	@Override
	public void dropIndex(String indexName) {
		getMongoCollection().dropIndex(indexName);
	}

	@Override
	public void dropIndex(String indexName, DropIndexOptions dropIndexOptions) {
		getMongoCollection().dropIndex(indexName, dropIndexOptions);
	}

	@Override
	public void dropIndex(Bson keys) {
		getMongoCollection().dropIndex(keys);
	}

	@Override
	public void dropIndex(Bson keys, DropIndexOptions dropIndexOptions) {
		getMongoCollection().dropIndex(keys, dropIndexOptions);
	}

	@Override
	public void dropIndex(ClientSession clientSession, String indexName) {
		getMongoCollection().dropIndex(clientSession, indexName);
	}

	@Override
	public void dropIndex(ClientSession clientSession, Bson keys) {
		getMongoCollection().dropIndex(clientSession, keys);
	}

	@Override
	public void dropIndex(ClientSession clientSession, String indexName, DropIndexOptions dropIndexOptions) {
		getMongoCollection().dropIndex(clientSession, indexName, dropIndexOptions);
	}

	@Override
	public void dropIndex(ClientSession clientSession, Bson keys, DropIndexOptions dropIndexOptions) {
		getMongoCollection().dropIndex(clientSession, keys, dropIndexOptions);
	}

	@Override
	public void dropIndexes() {
		getMongoCollection().dropIndexes();
	}

	@Override
	public void dropIndexes(ClientSession clientSession) {
		getMongoCollection().dropIndexes(clientSession);
	}

	@Override
	public void dropIndexes(DropIndexOptions dropIndexOptions) {
		getMongoCollection().dropIndexes(dropIndexOptions);
	}

	@Override
	public void dropIndexes(ClientSession clientSession, DropIndexOptions dropIndexOptions) {
		getMongoCollection().dropIndexes(clientSession, dropIndexOptions);
	}

	@Override
	public void renameCollection(MongoNamespace newCollectionNamespace) {
		getMongoCollection().renameCollection(newCollectionNamespace);
	}

	@Override
	public void renameCollection(MongoNamespace newCollectionNamespace,
			RenameCollectionOptions renameCollectionOptions) {
		getMongoCollection().renameCollection(newCollectionNamespace, renameCollectionOptions);
	}

	@Override
	public void renameCollection(ClientSession clientSession, MongoNamespace newCollectionNamespace) {
		getMongoCollection().renameCollection(clientSession, newCollectionNamespace);
	}

	@Override
	public void renameCollection(ClientSession clientSession, MongoNamespace newCollectionNamespace,
			RenameCollectionOptions renameCollectionOptions) {
		getMongoCollection().renameCollection(clientSession, newCollectionNamespace, renameCollectionOptions);
	}

}
